package gestores;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import servidor.Servidor;
import dados.Empresa;
import dados.Stock;

public class GestorStocks extends Thread {
	public final int INTERVALO_ENTRE_ACTUALIZACOES = 30000; //milissegundos

	private Servidor servidor;
	private GestorBD gestorBD;

	private LinkedList<String> symbols = new LinkedList<String>();
	private ArrayList<Stock> stocks = new ArrayList<Stock>();
	private ArrayList<Empresa> empresas = new ArrayList<Empresa>();
	
	
	public GestorStocks(Servidor servidor, GestorBD gestorBD) {
		//TODO Criar txt com os symbols, usar Amazon S3
		this.servidor = servidor;
		this.gestorBD = gestorBD;
		empresas = gestorBD.selectAllEmpresas();
		preencheListaSymbols();
	}
	
	public void preencheListaSymbols(){
		for (Empresa empresa : empresas) {
			symbols.add(empresa.getSigla());
		}
	}
	public void imprimeSymbols(){
		for (String symbol : symbols) {
			System.out.println(symbol);
		}
	}

	public boolean adicionaSymbol(String symbol) {
		if(!symbols.contains(symbol)){
			return symbols.add(symbol);
		}
		return false;
	}

	public boolean removeSymbol(String symbol) {
		for (int i = 0; i < symbols.size(); i++) {
			if (symbols.get(i).equals(symbol)) {
				symbols.remove(i);
				return true;
			}
		}
		return false;
	}

	public boolean actualizaStocks() {
		String stocksAActualizar = "";
		for (String symbol : symbols) {
			if (symbol.equals(symbols.getLast())) {
				stocksAActualizar += symbol;
			} else {
				stocksAActualizar += symbol + "+";
			}
		}
		try {
			stocks.clear();
			recebeLista(stocksAActualizar);

		} catch (Exception ex) {
			System.out.println("GestorStocks - Unable to get stockinfo for: " + stocksAActualizar +" - "+ ex);
			return false;
		}
		servidor.actualizarStocks(stocks);
		return true;
	}
	
	public boolean existeSigla(String sigla) {
		try{
			URL yahoofin = new URL("http://finance.yahoo.com/d/quotes.csv?s=" + sigla + "&f=snp2b3hgv");
			URLConnection yc = yahoofin.openConnection();
			BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
			String inputLine;
			while ((inputLine = in.readLine()) != null) {
//				System.out.println("INPUT: " + inputLine);
				ArrayList<String> yahooStockInfo = splitString(inputLine);
				Double.parseDouble(yahooStockInfo.get(3));
			}
			in.close();
		}catch(MalformedURLException e){
			e.printStackTrace();
			return false;
		}catch (NumberFormatException e) {
			System.out.println("Number Format Exception");
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		return true;
	}

	public void recebeLista(String stocksAActualizar) throws IOException  {
//		System.out.println("RECEBEU LISTA");
		try{
			URL yahoofin = new URL("http://finance.yahoo.com/d/quotes.csv?s=" + stocksAActualizar + "&f=snp2b3hgv");
			URLConnection yc = yahoofin.openConnection();
			BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
			String inputLine;
			
			while ((inputLine = in.readLine()) != null) {
//				System.out.println("INPUT: "+inputLine);
				ArrayList<String> yahooStockInfo = splitString(inputLine);
				Stock stockInfo = new Stock();
				stockInfo.setSigla(yahooStockInfo.get(0).replaceAll("\"", ""));
//				System.out.println("Sigla: " + stockInfo.getSigla());
				
				stockInfo.setNome(yahooStockInfo.get(1).replaceAll("\"", ""));
				stockInfo.setVariacao(Float.valueOf(yahooStockInfo.get(2).replaceAll("%", "").replaceAll("\"", "")));
				stockInfo.setCotacao(Float.valueOf(yahooStockInfo.get(3)));
				stockInfo.setValorAltoDia(Float.valueOf(yahooStockInfo.get(4).replaceAll("N/", "0.0")));
				stockInfo.setValorBaixoDia(Float.valueOf(yahooStockInfo.get(5).replaceAll("N/", "0.0")));
				stockInfo.setVolume(Integer.parseInt(yahooStockInfo.get(6)));
				stocks.add(stockInfo);
				
			}
			preencherDB(stocks);
			in.close();
		}catch(MalformedURLException e){
			e.printStackTrace();
		}catch (NumberFormatException e) {
			e.printStackTrace();
		}
	}
	
	public void preencherDB(ArrayList<Stock> stocks){
		ArrayList<Empresa> novasEmpresas = new ArrayList<Empresa>();
		for (Stock stock : stocks) {
			Empresa novaEmpresa = new Empresa(stock.getNome(), stock.getSigla());
			if (!existeEmpresa(novaEmpresa)){
				novasEmpresas.add(novaEmpresa);
				empresas.add(novaEmpresa);
			}
		}
		System.out.println("Insert Empresas affected " + gestorBD.insertSeveralEmpresas(novasEmpresas) + " row(s).");
		
		System.out.println("Insert Stocks affected " + gestorBD.insertSeveralStocks(stocks) + " row(s).");
	}
	
	public boolean existeEmpresa(Empresa novaEmpresa){
		for (Empresa empresa : empresas) {
			if (empresa.equals(novaEmpresa))
				return true;
		}
		return false;
	}

	public ArrayList<String> splitString(String yahoo){
		ArrayList<String> lista = new ArrayList<String>();
		for (int i = 0; i != yahoo.length(); i++) {
			if (yahoo.charAt(i) == '"') {
				int j = i + 1;
				while (yahoo.charAt(j) != '"') {
					j++;
				}
				lista.add(yahoo.substring(i + 1, j));
				yahoo = yahoo.substring(j + 2);
				i = -1;
			}else if(yahoo.charAt(i) == ','){
				lista.add(yahoo.substring(0, i - 1));
				yahoo = yahoo.substring(i+1);
				i = -1;
			}else if(!yahoo.contains(",")){
				lista.add(yahoo.substring(0));
			}
		}
		return lista;
	}

	public void imprimeStocks() {
		System.out.println();
		for (Stock stock : stocks) {
			System.out.println(stock);
		}
	}

	public ArrayList<Stock> getStocks(){
		return stocks;
	}

	@Override
	public void run() {
		setName("Thread StockManager - Servidor");
		int i = 0;
		try {
			while (true) {
				sleep(INTERVALO_ENTRE_ACTUALIZACOES);
				if(i == 10){
					gestorBD.deleteAllStocks(new Timestamp(new java.util.Date().getTime()));
					i = 0;
				}
				Date date = new Date();
				System.out.println("Data da Actualizacao: " + date.toString());
//				imprimeStocks();
				actualizaStocks();
				i++;
//				System.out.println("Insert Stocks affected " + gestorBD.insertSeveralStocks(stocks) + " row(s).");
				
			}
		} catch (InterruptedException e) {
			System.out.println("Thread Yahoo Interrompida...");
		}
	}
}
